package com.microframework.boot.system.service.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import com.jfinal.kit.StrKit;
import com.microframework.base.core.model.options.TreeNode;
import com.microframework.base.web.page.PageQuery;
import com.microframework.boot.system.model.domain.Menu;
import com.microframework.boot.system.model.domain.Role;
import com.microframework.boot.system.model.domain.RoleMenu;
import com.microframework.boot.system.model.domain.UserRole;
import com.microframework.boot.system.model.response.AuthItem;
import com.microframework.boot.system.model.response.SysRoute;
import com.microframework.boot.system.model.response.SysRouteMeta;
import com.microframework.boot.system.service.IMenuService;
import lombok.extern.slf4j.Slf4j;

@Service
@Slf4j
public class MenuServiceImpl implements IMenuService{

	@Override
	public List<SysRoute> getUserRoutes(String userId, String scope) {
	    // 参数校验
	    if (StrKit.isBlank(userId)) {
	        return Collections.emptyList();
	    }

	    // 构建基础SQL
	    StringBuilder sql = new StringBuilder("SELECT m.* FROM ")
	        .append(Menu.TABLE_NAME).append(" m ")
	        .append("WHERE m.is_del=? and m.id IN (")
	        .append("SELECT rm.menu_id FROM ").append(RoleMenu.TABLE_NAME).append(" rm ,").append(Role.TABLE_NAME).append(" r ")
	        .append("WHERE rm.role_id=r.id and r.enabled=0 and r.is_del=0 and rm.role_id IN (")
	        .append("SELECT ur.role_id FROM ").append(UserRole.TABLE_NAME).append(" ur ")
	        .append("WHERE ur.user_id = ?))");

	    // 添加scope条件
	    List<Object> params = new ArrayList<>();
	    params.add("0");
	    params.add(userId);
	    if (!StrKit.isBlank(scope)) {
	        sql.append(" AND m.scope = ?");
	        params.add(scope);
	    }
	    sql.append(" and m.enabled='0' order by m.sort asc ");
	    return buildRoutes(buildTree(Menu.dao.find(sql.toString(), params.toArray())));
	}
	
	private List<SysRoute> buildRoutes(List<Menu> menus){
		List<SysRoute> routes=new LinkedList<SysRoute>();
		if(menus!=null) {
			for(Menu menu:menus) {
				routes.add(buildRoute(menu));
			}
		}
		return routes;
	}
	
	private SysRoute buildRoute(Menu menu){
		SysRoute route=new SysRoute();
		route.setId(menu.getId());
        route.setName(menu.getCode());
        route.setPath(menu.getPath());
        route.setComponent(menu.getComponent());
        SysRouteMeta meta= new SysRouteMeta();
        
        meta.setCnTitle(menu.getCnName());
        meta.setEnTitle(menu.getEnName());
        if(!StrKit.isBlank(menu.getIcon())) {
        	meta.setIcon(menu.getIcon());
        }
        
        meta.setFixedTab(StrKit.equals("0", menu.getFixed()));
        meta.setHide(StrKit.equals("1", menu.getShow()));
        meta.setHideTab(meta.isHide());
        meta.setKeepAlive(StrKit.equals("0", menu.getKeepAlive()));
        meta.setIframe(StrKit.equals("0", menu.getIsIframe()));
        meta.setLink(menu.getLink());
        
        
        
        if(StrKit.equals(menu.getType(), "menu")) {
        	if(menu.getChildren()!=null && menu.getChildren().size()>0) {
        		List<Menu> btnList=menu.getChildren();
	        	List<AuthItem> authList=new LinkedList<AuthItem>();
	        	AuthItem authItem;
	        	for(Menu btn:btnList) {
	        		authItem=new AuthItem();
	        		authItem.setId(btn.getId());
	        		authItem.setAuthMark(btn.getCode());
	        		authItem.setCnTitle(btn.getCnName());
	        		authItem.setEnTitle(btn.getEnName());
	        		authList.add(authItem);
	        	}
	        	meta.setAuthList(authList);
        	}
        }
        else if(StrKit.equals(menu.getType(), "folder")) {
        	if(menu.getChildren()!=null && menu.getChildren().size()>0) {
        		route.setChildren(buildRoutes(menu.getChildren()));
        	}
        }
        route.setMeta(meta);
		return route;
	}
	
	public List<Menu> buildTree(List<Menu> nodes) {
	    // 1. 创建快速查找映射表
	    Map<String, Menu> nodeMap = new HashMap<>();
	    Map<String, List<Menu>> parentChildMap = new HashMap<>();
	    
	    // 2. 构建索引
	    for (Menu node : nodes) {
	        String nodeId = node.getId();
	        String parentId = node.getParentId();
	        
	        // 存储节点映射
	        nodeMap.put(nodeId, node);
	        
	        // 构建父子关系映射
	        parentChildMap.computeIfAbsent(parentId, k -> new ArrayList<>()).add(node);
	    }
	    
	    // 3. 识别根节点（没有父节点或父节点不存在）
	    List<Menu> roots = new ArrayList<>();
	    for (Menu node : nodes) {
	        String parentId = node.getParentId();
	        
	        // 根节点条件：父节点为空、不存在或指向自身（根据业务需求调整）
	        if (parentId == null || 
	            !nodeMap.containsKey(parentId) || 
	            parentId.equals(node.getId())) {
	            roots.add(node);
	        }
	    }
	    
	    // 4. 递归构建树形结构
	    roots.forEach(root -> buildTreeRecursive(root, parentChildMap));
	    
	    return roots;
	}

	private void buildTreeRecursive(Menu node, Map<String, List<Menu>> parentChildMap) {
	    String nodeId = node.getId();
	    List<Menu> children = parentChildMap.get(nodeId);
	    
	    if (children != null && !children.isEmpty()) {
	        // 设置子节点并继续递归构建
	        node.setChildren(children);
	        children.forEach(child -> buildTreeRecursive(child, parentChildMap));
	    }
	}

	@Override
	public List<TreeNode<Menu>> tree(PageQuery<Menu> pageQuery) {
		try {
			String select="select id,parent_id,cn_name,en_name,code,sort ";
			StringBuilder sqlBuilder = new StringBuilder(select+" FROM " + Menu.TABLE_NAME + " WHERE 1=1");
			List<Object> params = new ArrayList<>();

			Menu query = pageQuery.getQuery();
			if (query != null) {
				// 构建查询条件

				if (StringUtils.hasText(query.getCnName())) {
					sqlBuilder.append(" AND cn_name LIKE ?");
					params.add("%" + query.getCnName() + "%");
				}
				
				if (StringUtils.hasText(query.getEnName())) {
					sqlBuilder.append(" AND en_name LIKE ?");
					params.add("%" + query.getEnName() + "%");
				}
				
				if (StringUtils.hasText(query.getCode())) {
					sqlBuilder.append(" AND code LIKE ?");
					params.add("%" + query.getCode() + "%");
				}
				
				if (StringUtils.hasText(query.getParentId())) {
					sqlBuilder.append(" AND parent_id = ?");
					params.add(query.getParentId());
				}
				
				if (StringUtils.hasText(query.getIsDel())) {
					sqlBuilder.append(" AND is_del = ?");
					params.add(query.getIsDel());
				}else {
					sqlBuilder.append(" AND is_del = ?");
					params.add("0");
				}
			}

			// 设置排序
			String orderBy = StringUtils.hasText(pageQuery.getOrderBy()) ? pageQuery.getOrderBy() : " sort";
			String orderDirection = StringUtils.hasText(pageQuery.getOrderDirection()) ? pageQuery.getOrderDirection()
					: "desc";
			sqlBuilder.append(" ORDER BY " + orderBy + " " + orderDirection);
			
			List<Menu> orgs=Menu.dao.find(sqlBuilder.toString(), params.toArray());
			
			List<TreeNode<Menu>> treeNodes = orgs.stream()
				    .map(org -> {
				    	TreeNode<Menu> treeNode=new TreeNode<Menu>();
				    	treeNode.setId(org.getId());
				    	treeNode.setParentId(org.getParentId());
				    	treeNode.setLabel(org.getCnName());
				    	treeNode.setExtend(org);
				    	return treeNode;
				    })
				    .collect(Collectors.toList());
			
			return recurOptions(treeNodes);
		} catch (Exception e) {
			log.error("查询下拉树异常{}", e.getMessage());
			return new LinkedList<TreeNode<Menu>>();
		}
	}
	
	
	public List<TreeNode<Menu>> recurOptions(List<TreeNode<Menu>> allNodes) {
	    // 1. 创建快速查找映射
	    Map<String, TreeNode<Menu>> nodeMap = new HashMap<>();
	    Map<String, List<TreeNode<Menu>>> parentChildMap = new HashMap<>();
	    
	    // 2. 构建索引
	    for (TreeNode<Menu> node : allNodes) {
	        String id = node.getId();
	        String parentId = node.getParentId();
	        
	        // 存储节点映射
	        nodeMap.put(id, node);
	        
	        // 构建父子关系映射
	        parentChildMap.computeIfAbsent(parentId, k -> new ArrayList<>()).add(node);
	    }
	    
	    // 3. 识别根节点（自动处理多种情况）
	    List<TreeNode<Menu>> roots = new ArrayList<>();
	    for (TreeNode<Menu> node : allNodes) {
	        String parentId = node.getParentId();
	        
	        // 根节点条件：父节点为空/不存在/等于自身ID
	        if (parentId == null || 
	            !nodeMap.containsKey(parentId) || 
	            parentId.equals(node.getId())) {
	            roots.add(node);
	        }
	    }
	    
	    // 4. 递归构建树形结构
	    roots.forEach(root -> buildChildren(root, parentChildMap));
	    return roots;
	}

	private void buildChildren(TreeNode<Menu> node, Map<String, List<TreeNode<Menu>>> parentChildMap) {
	    String nodeId = node.getId();
	    List<TreeNode<Menu>> children = parentChildMap.get(nodeId);
	    
	    if (children != null && !children.isEmpty()) {
	        // 设置子节点并继续递归构建
	        node.setChildren(children);
	        children.forEach(child -> buildChildren(child, parentChildMap));
	    }
	}

	@Override
	public List<Menu> loadAll(PageQuery<Menu> pageQuery) {
		try {
			String select="select * ";
			StringBuilder sqlBuilder = new StringBuilder(select+" FROM " + Menu.TABLE_NAME + " WHERE 1=1");
			List<Object> params = new ArrayList<>();

			Menu query = pageQuery.getQuery();
			if (query != null) {
				// 构建查询条件

				if (StringUtils.hasText(query.getCnName())) {
					sqlBuilder.append(" AND cn_name LIKE ?");
					params.add("%" + query.getCnName() + "%");
				}
				
				if (StringUtils.hasText(query.getEnName())) {
					sqlBuilder.append(" AND en_name LIKE ?");
					params.add("%" + query.getEnName() + "%");
				}
				
				if (StringUtils.hasText(query.getCode())) {
					sqlBuilder.append(" AND code LIKE ?");
					params.add("%" + query.getCode() + "%");
				}
				
				if (StringUtils.hasText(query.getParentId())) {
					sqlBuilder.append(" AND parent_id = ?");
					params.add(query.getParentId());
				}
				
				if (StringUtils.hasText(query.getIsDel())) {
					sqlBuilder.append(" AND is_del = ?");
					params.add(query.getIsDel());
				}else {
					sqlBuilder.append(" AND is_del = ?");
					params.add("0");
				}
			}

			// 设置排序
			String orderBy = StringUtils.hasText(pageQuery.getOrderBy()) ? pageQuery.getOrderBy() : " sort";
			String orderDirection = StringUtils.hasText(pageQuery.getOrderDirection()) ? pageQuery.getOrderDirection()
					: " asc ";
			sqlBuilder.append(" ORDER BY " + orderBy + " " + orderDirection);
			List<Menu> menus=Menu.dao.find(sqlBuilder.toString(), params.toArray());
			return buildTree(menus);
		} catch (Exception e) {
			log.error("查询异常{}", e.getMessage());
			return new LinkedList<Menu>();
		}
	}

	@Override
	public List<Menu> loadLazy(PageQuery<Menu> pageQuery) {
		try {
			String select="select m.*,IFNULL((SELECT COUNT(id) FROM "+Menu.TABLE_NAME+" WHERE parent_id = m.id  and is_del=0 ), 0) > 0 AS has_children ";
			StringBuilder sqlBuilder = new StringBuilder(select+" FROM " + Menu.TABLE_NAME + " m WHERE 1=1");
			List<Object> params = new ArrayList<>();

			Menu query = pageQuery.getQuery();
			if (query != null) {
				// 构建查询条件

				if (StringUtils.hasText(query.getCnName())) {
					sqlBuilder.append(" AND m.cn_name LIKE ?");
					params.add("%" + query.getCnName() + "%");
				}
				
				if (StringUtils.hasText(query.getEnName())) {
					sqlBuilder.append(" AND m.en_name LIKE ?");
					params.add("%" + query.getEnName() + "%");
				}
				
				if (StringUtils.hasText(query.getCode())) {
					sqlBuilder.append(" AND m.code LIKE ?");
					params.add("%" + query.getCode() + "%");
				}
				
				if (StringUtils.hasText(query.getParentId())) {
					sqlBuilder.append(" AND m.parent_id = ?");
					params.add(query.getParentId());
				}
				
				if (StringUtils.hasText(query.getIsDel())) {
					sqlBuilder.append(" AND m.is_del = ?");
					params.add(query.getIsDel());
				}else {
					sqlBuilder.append(" AND m.is_del = ?");
					params.add("0");
				}
			}

			// 设置排序
			String orderBy = StringUtils.hasText(pageQuery.getOrderBy()) ? "m."+pageQuery.getOrderBy() : " m.sort";
			String orderDirection = StringUtils.hasText(pageQuery.getOrderDirection()) ? pageQuery.getOrderDirection()
					: " asc ";
			sqlBuilder.append(" ORDER BY " + orderBy + " " + orderDirection);
			return Menu.dao.find(sqlBuilder.toString(), params.toArray());
		} catch (Exception e) {
			log.error("查询异常{}", e.getMessage());
			return new LinkedList<Menu>();
		}
	}
	

}
